home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / comm / bbs / cit_src_7H21.lha / msgadd.c < prev    next >
C/C++ Source or Header  |  1997-07-27  |  34KB  |  1,527 lines

  1. /*
  2.  *                              msgadd.c
  3.  *
  4.  * External Message handler.  For use with external OtherNet parsers.
  5.  */
  6. #define VIEWING (1)
  7. /*
  8.  *                              history
  9.  *
  10.  * 96Sep01 AFP  V1.5 -- support vortex checking and archiving by month & year
  11.  * 91Mar31 HAW  v1.4 -- support for virtual rooms.
  12.  * 90Aug13 HAW  v1.3 -- support for room archiving.
  13.  * 89Oct23 HAW  v1.2 -- support for incoming route mail.
  14.  * 88Nov05 HAW  Created.
  15.  */
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <math.h>
  19. #include <time.h>
  20. #include "ctdl.h"
  21. /*
  22.  *                              contents
  23.  *
  24.  */
  25.  
  26. #define TITLE           "C86Net Message Importer"
  27.  
  28. int debug_flag=0;
  29. int force_flag=0;
  30.  
  31. #define NO_ERROR        0
  32. #define BAD_ARGS        1
  33. #define BAD_TABLE       2
  34. #define NO_NODE         3
  35. #define FATAL           4
  36. #define LF_ERROR        5
  37.  
  38. int       crtColumn;
  39. extern CONFIG cfg;                /* Configuration variables      */
  40. extern MessageBuffer msgBuf;      /* The -sole- message buffer    */
  41. extern aRoom roomBuf;             /* Room buffer  */
  42. extern logBuffer logBuf;
  43. extern FILE *roomfl,
  44.          *logfl;
  45. extern int thisRoom;              /* Current room */
  46. extern rTable *roomTab;
  47. extern struct mBuf mFile1,
  48.           mFile2;
  49. extern NetTable *netTab;
  50. extern NetBuffer netBuf;
  51. extern NetBuffer netTemp;
  52. extern FILE *netfl;
  53. extern LogTable *logTab;
  54. extern int thisNet;               /* Current node in use  */
  55. extern char *APPEND_ANY;
  56. extern char *APPEND_TEXT;
  57. extern FILE *msgfl,
  58.          *msgfl2;
  59. FILE     *GlobalFd;
  60. int       RouteSlot;
  61. extern FILE *upfd;
  62. char      inNet = NORMAL_NET;
  63.  
  64. FILE     *netLog = stderr;
  65. char      logNetResults = TRUE;
  66. char      netDebug = TRUE;
  67.  
  68. SListBase MailForward =
  69. {NULL, NULL, NULL, NULL, NULL};
  70. SListBase Arch_base =
  71. {NULL, ChkNtoStr, NULL, FreeNtoStr, EatNMapStr};
  72. static char EOP = FALSE;
  73. char     *R_SH_MARK = "&&";
  74. char     *NON_LOC_NET = "%%";
  75. char     *LOC_NET = "++";
  76.  
  77. /**
  78.   Some statistics variables
  79. **/
  80. int total_msgs    = 0; /* total messages processed */
  81. int vortex_msgs   = 0; /* rejected messages due to vortexes */
  82. int added_msgs    = 0; /* messages added */
  83. int rejected_msgs = 0; /* message  rejected for other reasons */
  84.  
  85.  
  86. void      GenInit (void);
  87. void      Process (char *fn);
  88. int       GetOtherNetChar (void);
  89. int       VirtualShared (int NetNo, label name);
  90. int       VirtualExists (label name);
  91. void      SaveIt (void);
  92. int       FindRoom (label nm);
  93. int       FindNet (label nm, NetBuffer * netBuf);
  94. void      AddVirtualField (char field, char *contents);
  95. void      PutMessage (void);
  96. void      HandleRouted (void);
  97. void      AddField (int field, char *fValue);
  98. int       FindPos (void);
  99. void      VirtualHandle (void);
  100. int       MARecVirtualRoom (int VirtIndex);
  101. void      TranslateFilename (char *realfn, char *fn);
  102. void      netResult (char *);
  103. char      Check_Address(label mbaddr );
  104. void      Fix_Name(char *out, char *in, int flag);
  105.  
  106. int
  107. mPrintf (char *format,...)
  108. {
  109.   return 0;
  110. }       /* stub to quiet the linker */
  111.  
  112. /*
  113.  * crashout()
  114.  *
  115.  * Big error handler.
  116.  */
  117. void
  118. crashout (str)
  119.   char     *str;
  120. {
  121.   printf (str);
  122.   exit (FATAL);
  123. }
  124.  
  125. /*
  126.  * main()
  127.  *
  128.  * This is the main manager.
  129.  */
  130. int       main (int, char **);
  131. int
  132. main (argc, argv)
  133.   char    **argv;
  134.   int       argc;
  135. {
  136.   int       rover;
  137.   printf ("%s %s\n%s\n\n", TITLE, VERSION_NAME, COPYRIGHT);
  138.   if (argc < 3)
  139.     {
  140.       printf ("usage: MSGADD <options>  nodename file [ file ... ]\n");
  141.       printf (" options:  -f  == force adding of messages even if not shared\n");
  142.       printf ("           -d  == debug information \n");
  143.       printf ("\nEach file may contain one or more messages in C86Net format.\n");
  144.       exit (BAD_ARGS);
  145.     }
  146.   /**
  147.     First scan for any options.
  148.   **/
  149.   for( rover=1; rover < argc && argv[rover][0] == '-'; rover++)
  150.     {
  151.     if( argv[rover][1] == 'f' || argv[rover][1] == 'F' )force_flag = 1;
  152.     if( argv[rover][1] == 'd' || argv[rover][1] == 'D' )debug_flag = 1;
  153.     };
  154.   cfg.weAre = UTILITY;
  155.   if (!readSysTab (TRUE, TRUE))
  156.     {
  157.       exit (BAD_TABLE);
  158.     }
  159.  
  160.   if (access (LOCKFILE, 0) != -1)
  161.     {
  162.       printf ("Please do not run MsgAdd using Outside Commands.\n");
  163.       writeSysTab ();
  164.       exit (LF_ERROR);
  165.     }
  166.  
  167.   GenInit ();
  168.   VirtInit ();
  169.   VortexInit ();
  170.   InitVortexing ();
  171.  
  172.   /**
  173.     find the first non-option argument and use as
  174.     the node name
  175.   **/
  176.   for( rover=1; rover < argc && argv[rover][0] == '-'; rover++)
  177.     ;
  178.  
  179.   if (FindNet (argv[rover], &netBuf) == ERROR)
  180.     {
  181.       writeSysTab ();
  182.       printf ("Could not find node %s.\n", argv[rover]);
  183.       exit (NO_NODE);
  184.     };
  185.  
  186.   for (rover++ ; rover < argc; rover++)
  187.     if( argv[rover][0] != '-' )Process (argv[rover]);
  188.   strcpy(msgBuf.mbtext,"No Vortex Problems found\n");
  189.   FinVortexing ();      /* cleanup and report errors */
  190.   printf(msgBuf.mbtext);
  191.   UpdVirtStuff ();
  192.   writeSysTab ();
  193.   printf(" %d vortex, %d rejected, %d added messaged\n",
  194.   vortex_msgs, rejected_msgs, added_msgs);
  195.   printf(" %d total messages processed\n", total_msgs);
  196.   return 0;
  197. }
  198.  
  199. /*
  200.  * GenInit()
  201.  *
  202.  * This is a general initialization routine.
  203.  */
  204. void
  205. GenInit ()
  206. {
  207.   SYS_FILE  fn;
  208.  
  209.   initNetBuf (&netBuf);
  210.   initNetBuf (&netTemp);
  211.   makeSysName (fn, "ctdlnet.sys", &cfg.netArea);
  212.   openFile (fn, &netfl);
  213.  
  214.   initRoomBuf (&roomBuf);
  215.   makeSysName (fn, "ctdlroom.sys", &cfg.roomArea);
  216.   openFile (fn, &roomfl);
  217.  
  218.   InitMsgBase ();
  219.  
  220.   initLogBuf (&logBuf);
  221.   makeSysName (fn, "ctdllog.sys", &cfg.logArea);
  222.   openFile (fn, &logfl);
  223.  
  224.   makeSysName (fn, "ctdlarch.sys", &cfg.roomArea);
  225.   MakeList (&Arch_base, fn, NULL);
  226. }
  227.  
  228. /*
  229.  * Process()
  230.  *
  231.  * This will process a file - read a file for all messages and stuff them
  232.  * into the message base.
  233.  */
  234. void
  235. Process (fn)
  236.   char     *fn;
  237. {
  238.   extern char *READ_ANY;
  239.  
  240.   if ((GlobalFd = fopen (fn, READ_ANY)) == NULL)
  241.     {
  242.       printf ("ERROR: Could not open %s.\n", fn);
  243.       return;
  244.     }
  245.  
  246.   while (getMessage (GetOtherNetChar, TRUE, TRUE, TRUE))
  247.     SaveIt ();
  248.  
  249.   fclose (GlobalFd);
  250. }
  251.  
  252. /*
  253.  * GetOtherNetChar()
  254.  *
  255.  * This gets a character for getMessage.
  256.  */
  257. int
  258. GetOtherNetChar ()
  259. {
  260.   int       c;
  261.  
  262.   c = getc (GlobalFd);
  263.   if (c == EOF)
  264.     return -1;
  265.   return c;
  266. }
  267.  
  268. /*
  269.  * SaveIt()
  270.  *
  271.  * This is charged with saving the message in the database.
  272.  *
  273.  * 1. If mail, must do recipient validation.
  274.  * 2. Must validate room.
  275.  */
  276. void
  277. SaveIt ()
  278. {
  279.   int       LogSlot,
  280.             RoomSlot,
  281.             place;
  282.   extern char *NON_LOC_NET,
  283.            *LOC_NET;
  284.   char     *fn,
  285.            *realfn;
  286.   total_msgs++;
  287.   if( debug_flag )
  288.     {
  289.     printf ("mbauth =-%s-\t", msgBuf.mbauth);
  290.     printf ("mbroom =-%s-\n", msgBuf.mbroom);
  291.     printf ("mbdate =-%s-\t", msgBuf.mbdate);
  292.     printf ("mbtime =-%s-\n", msgBuf.mbtime);
  293.     printf ("mboname=-%s-\t", msgBuf.mboname);
  294.     printf ("mborig =-%s-\n", msgBuf.mborig);
  295.     printf ("mbto   =-%s-\t", msgBuf.mbto);
  296.     printf ("mbsrcId=-%s-\n", msgBuf.mbsrcId);
  297.     };
  298.   if (VirtualExists (msgBuf.mbroom) != ERROR)
  299.     {
  300.       VirtualHandle ();
  301.       return;
  302.     };
  303.  
  304.   if (Check_Address(msgBuf.mbaddr) != 0)
  305.     {
  306.       HandleRouted ();
  307.     }
  308.   else if (strCmpU (msgBuf.mbroom, "mail") == SAMESTRING)
  309.     {
  310.       if( strCmpU(msgBuf.mbto, "sysop") == SAMESTRING )
  311.         {
  312.         strcpy(msgBuf.mbto, cfg.SysopName);
  313.         };
  314.       if ((LogSlot = findPerson (msgBuf.mbto, &logBuf)) == ERROR)
  315.         {
  316.           printf ("Could not deliver Mail to '%s', does not exist.\n",
  317.                   msgBuf.mbto);
  318.           rejected_msgs++;
  319.           return;
  320.         }
  321.       noteAMessage (logBuf.lbMail, MAILSLOTS, cfg.newest + 1, cfg.catSector);
  322.       putLog (&logBuf, LogSlot);
  323.     }
  324.   else
  325.     {
  326.       if ((RoomSlot = FindRoom (msgBuf.mbroom)) == ERROR)
  327.         {
  328.           printf ("Message meant for non-existent room '%s' not incorporated.\n",
  329.                   msgBuf.mbroom);
  330.           rejected_msgs++;
  331.           return;
  332.         };
  333.       if( debug_flag ) printf(" RoomSlot:%d\n",RoomSlot);
  334.       /**
  335.          Validate that the rooms is shared properly, ignored if we have force
  336.       **/
  337.       if ((place = FindPos ()) == ERROR)
  338.         {
  339.         printf ("WARNING: msg for %s is not formally shared, discarded.\n",
  340.                 msgBuf.mbroom);
  341.         if( force_flag == 0 )
  342.           {
  343.           rejected_msgs++;
  344.           return;
  345.           };
  346.         };
  347.       /**
  348.          Do vortex checking
  349.       **/
  350.       if (!NotVortex ())
  351.         {
  352.           printf ("Vortex detected, message is a duplicate, not incorporated.\n");
  353.           printf ("Author:%20s   ", msgBuf.mbauth);
  354.           printf ("Room:%s\n", msgBuf.mbroom);
  355.           printf ("  date:%20s   ", msgBuf.mbdate);
  356.           printf ("time:%s\n", msgBuf.mbtime);
  357.           printf (" Oname:%20s   ", msgBuf.mboname);
  358.           printf ("orig:%s\n", msgBuf.mborig);
  359.           printf ("    to:%20s   ", msgBuf.mbto);
  360.           printf (" src:%s\n\n", msgBuf.mbsrcId);
  361.           vortex_msgs++;
  362.           return;
  363.         };
  364.  
  365.       noteAMessage (roomBuf.msg, MSGSPERRM, cfg.newest + 1, cfg.catSector);
  366.       roomTab[RoomSlot].rtlastMessage = cfg.newest + 1;
  367.       putRoom (RoomSlot);
  368.       if( place != ERROR )
  369.         {
  370.         if (roomBuf.rbShareType != PEON && netBuf.netRooms[place].mode != PEON)
  371.           strCpy (msgBuf.mbaddr, NON_LOC_NET);
  372.         else
  373.           strCpy (msgBuf.mbaddr, LOC_NET);
  374.         };
  375.  
  376.       if (roomBuf.rbflags.ARCHIVE == 1)
  377.         {
  378.           fn = SearchList (&Arch_base, NtoStrInit (thisRoom, "", 0, TRUE));
  379.           realfn = GetDynamic (strlen (fn) + 15);
  380.           TranslateFilename (realfn, fn);
  381.           if( debug_flag ) printf(" Filename;%s is now %s\n",fn,realfn);
  382.           if ((upfd = fopen (realfn, APPEND_TEXT)) != NULL)
  383.             {
  384.               if (msgBuf.mbdate[0])fprintf (upfd, "   %s ", msgBuf.mbdate);
  385.               if (msgBuf.mbtime[0] && sendTime)fprintf (upfd, "%s ", msgBuf.mbtime);
  386.               if (msgBuf.mbauth[0]) fprintf (upfd, "from %s", msgBuf.mbauth);
  387.               NormStr (msgBuf.mboname);
  388.               if (msgBuf.mboname[0])
  389.                 {
  390.                   fprintf (upfd, " @ %s", msgBuf.mboname);
  391.                   if (msgBuf.mbdomain[0])fprintf (upfd, cfg.DomainDisplay, msgBuf.mbdomain);
  392.                 };
  393.  
  394.               if (msgBuf.mbto[0]) fprintf (upfd, " to %s", msgBuf.mbto);
  395.               crtColumn = 1;
  396.               mFormat (msgBuf.mbtext);
  397.               fprintf (upfd, "\n");
  398.               fclose (upfd);
  399.             };
  400.           free(realfn);
  401.         }
  402.     }
  403.   /**  probably don't need this... strCpy (msgBuf.mborig, netBuf.netId); **/
  404.   PutMessage ();
  405.   cfg.newest++;
  406.   added_msgs++;
  407.   cfg.catSector = mFile1.thisSector;
  408.   cfg.catChar = mFile1.thisChar;
  409. }
  410.  
  411. SListBase FwdAliasii;             /* keeps some other stuff happy */
  412. char      onConsole = FALSE,
  413.           remoteSysop = FALSE;
  414. int       callSlot = ERROR;
  415.  
  416. /*
  417.  * HandleRouted()
  418.  *
  419.  * This should handle mail routing incoming.
  420.  */
  421. void
  422. HandleRouted ()
  423. {
  424.   char     *AltName;
  425.   label     Name,
  426.             Id,
  427.             temp;
  428.   SYS_FILE  fn;
  429.   extern void (*NetPrintTarget) (char *fmt,...);
  430.   extern int (*ToFileWork) ();
  431.  
  432. /* no find? */
  433.   if ((RouteSlot = FindNet (msgBuf.mbaddr, &netTemp)) == ERROR)
  434.     {
  435.       return;
  436.     }
  437.  
  438. /* yes, found, data in netTemp - will we do the routing? */
  439.   if (!cfg.BoolFlags.RouteMail || !netTemp.nbflags.RouteTo)
  440.     {
  441.       return;
  442.     }
  443.  
  444. /* yes, we'll do the routing.  Now to figure it out. */
  445.   strCpy (Name, netTemp.netName);
  446.   strCpy (Id, netTemp.netId);
  447.  
  448.   if ((AltName = UseNetAlias (Name, TRUE)) != NULL)
  449.     strCpy (Name, AltName);
  450.  
  451.   if (FindRouteSlot () == ERROR)
  452.     {
  453.       return;
  454.     }
  455.  
  456. /* Ugly ugly kludge until we figure out how nbHiRouteInd is wrong */
  457.   if (netTemp.nbHiRouteInd < 0)
  458.     netTemp.nbHiRouteInd = 0;
  459.   sPrintf (temp, "R%d.%d", RouteSlot, netTemp.nbHiRouteInd++);
  460.  
  461.   makeSysName (fn, temp, &cfg.netArea);
  462.  
  463.   if ((upfd = safeopen (fn, APPEND_ANY)) == NULL)
  464.     {
  465.       return;
  466.     }
  467.  
  468.   fprintf (upfd, "%-20s", Id);
  469.   putc (0, upfd);
  470.   fprintf (upfd, "%-20s", Name);
  471.   putc (0, upfd);
  472.  
  473.   NetPrintTarget = ToFile;
  474.   StartEncode (putFLChar);
  475.   ToFileWork = Encode;
  476.   prNetStyle (TRUE, Encode, FALSE, "");
  477.   StopEncode ();
  478.   fclose (upfd);
  479.   netTemp.nbflags.HasRouted = TRUE;
  480.  
  481.   putNet (RouteSlot, &netTemp);
  482.   added_msgs++;
  483. }
  484.  
  485. /*
  486.  * findRoom()
  487.  *
  488.  * This function should find the named room.  Return ERROR if not found.
  489.  */
  490. int
  491. FindRoom (nm)
  492.   label     nm;
  493. {
  494.   int       rover;
  495.  
  496.   for (rover = 0; rover < MAXROOMS; rover++)
  497.     if (strCmpU (roomTab[rover].rtname, nm) == SAMESTRING)
  498.       {
  499.         getRoom (rover);
  500.         return rover;
  501.       }
  502.  
  503.   return ERROR;
  504. }
  505.  
  506. /*
  507.  * noteAMessage()
  508.  *
  509.  * This function notes a message in a message array.  Stolen from MSG.C.
  510.  */
  511. void
  512. noteAMessage (base, slots, id, loc)
  513.   MSG_NUMBER id;
  514.   SECTOR_ID loc;
  515.   theMessages *base;
  516.   int       slots;
  517. {
  518.   int       i;
  519.  
  520. /* store into current room: */
  521. /* slide message pointers down to make room for this one:       */
  522.   for (i = 0; i < slots - 1; i++)
  523.     {
  524.       base[i].rbmsgLoc = base[i + 1].rbmsgLoc;
  525.       base[i].rbmsgNo = base[i + 1].rbmsgNo;
  526.     }
  527.  
  528. /* slot this message in:    */
  529.   base[slots - 1].rbmsgNo = id;
  530.   base[slots - 1].rbmsgLoc = loc;
  531. }
  532.  
  533. /*
  534.  * FindNet()
  535.  *
  536.  * This function will find the named node.  Stolen from searchNameNet/NETMISC.
  537.  */
  538. int
  539. FindNet (label nm, NetBuffer * nBuf)
  540. {
  541.   int       rover;
  542.  
  543.   for (rover = 0; rover < cfg.netSize; rover++)
  544.     {
  545.       if (netTab[rover].ntflags.in_use &&
  546.           hash (nm) == netTab[rover].ntnmhash)
  547.         {
  548.           getNet (rover, nBuf);
  549.           if (strCmpU (nBuf->netName, nm) == SAMESTRING)
  550.             return rover;
  551.         }
  552.     }
  553.   return ERROR;
  554. }
  555.  
  556. /*
  557.  * FindPos()
  558.  *
  559.  * This finds the spot in the shared room array for the node that matches up
  560.  * with the current room.
  561.  */
  562. int
  563. FindPos ()
  564. {
  565.   int       rover;
  566.  
  567.   for (rover = 0; rover < SHARED_ROOMS; rover++)
  568.     if (isSharedRoom (thisNet, rover) &&
  569.         netRoomSlot (rover) == thisRoom &&
  570.         netGen (thisNet, rover) == roomBuf.rbgen)
  571.       return rover;
  572.  
  573.   return ERROR;
  574. }
  575.  
  576. /*
  577.  * VirtualHandle()
  578.  *
  579.  * This function will handle a message destined for a virt room.
  580.  */
  581. void
  582. VirtualHandle ()
  583. {
  584.   int       Vindex;
  585.  
  586.   if ((Vindex = VirtualShared (thisNet, msgBuf.mbroom)) == ERROR)
  587.     {
  588.       printf ("Virtual room %s not shared with %s, message not saved.\n",
  589.               msgBuf.mbroom, netBuf.netName);
  590.       return;
  591.     }
  592.   MARecVirtualRoom (Vindex);
  593. }
  594.  
  595. /*********** These functions stolen & modified from VIRT2.C ***************/
  596.  
  597. extern VirtualRoom *VRoomTab;
  598. extern VirtNet *VirtNetList;
  599. extern int VirtSize,
  600.           VNetSize;
  601.  
  602. /*
  603.  * MARecVirtualRoom()
  604.  *
  605.  * This function receives a virtual room from another system.
  606.  */
  607. int
  608. MARecVirtualRoom (int VirtIndex)
  609. {
  610.   int       VirtNo;
  611.   MSG_NUMBER rover;
  612.   char     *distance,
  613.             fn[50];
  614.   extern FILE *upfd;
  615.   extern char *WRITE_ANY;
  616.  
  617.   VirtNo = VirtNetList[thisNet].VirtList[VirtIndex].WhichVirt;
  618.  
  619.   if (VirtNetList[thisNet].VirtList[VirtIndex].mode != PEON)
  620.     {
  621.       distance = LD_DIR;
  622.       rover = VRoomTab[VirtNo].vrHiLD + 1l;
  623.       VRoomTab[VirtNo].vrChanged |= LD_CHANGE;
  624.     }
  625.   else
  626.     {
  627.       distance = LOCAL_DIR;
  628.       rover = VRoomTab[VirtNo].vrHiLocal + 1l;
  629.       VRoomTab[VirtNo].vrChanged |= LOC_CHANGE;
  630.     }
  631.   CreateVAName (fn, VirtNo, distance, rover);
  632.  
  633.   if ((upfd = fopen (fn, WRITE_ANY)) != NULL)
  634.     {
  635.       if (msgBuf.mbauth[0])
  636.         AddVirtualField ('A', msgBuf.mbauth);
  637.       if (msgBuf.mbdate[0])
  638.         AddVirtualField ('D', msgBuf.mbdate);
  639.       if (msgBuf.mbtime[0])
  640.         AddVirtualField ('C', msgBuf.mbtime);
  641.       if (msgBuf.mboname[0])
  642.         AddVirtualField ('N', msgBuf.mboname);
  643.       if (msgBuf.mborig[0])
  644.         AddVirtualField ('O', msgBuf.mborig);
  645.       if (msgBuf.mbroom[0])
  646.         AddVirtualField ('R', msgBuf.mbroom);
  647.       if (msgBuf.mbsrcId[0])
  648.         AddVirtualField ('S', msgBuf.mbsrcId);
  649.       if (msgBuf.mbto[0])
  650.         AddVirtualField ('T', msgBuf.mbto);
  651.       if (msgBuf.mbOther[0])
  652.         AddVirtualField ('P', msgBuf.mbOther);
  653.       if (msgBuf.mbdomain[0])
  654.         AddVirtualField ('X', msgBuf.mbdomain);
  655.       if (msgBuf.mbtext[0])
  656.         AddVirtualField ('M', msgBuf.mbtext);
  657.       fclose (upfd);
  658.     }
  659.   else
  660.     printf ("Unable to open %s!\n", fn);
  661.  
  662.   VirtSummary ();
  663.   return 0;
  664. }
  665.  
  666. /*
  667.  * AddVirtualField()
  668.  *
  669.  * This function adds a field to a virtual room message.
  670.  */
  671. void
  672. AddVirtualField (char field, char *contents)
  673. {
  674.   fprintf (upfd, "%c%s", field, contents);
  675.   fputc (0, upfd);
  676. }
  677.  
  678. /*
  679.  * VirtualExists()
  680.  *
  681.  * This function returns an index to given room, if exists.
  682.  */
  683. int
  684. VirtualExists (label name)
  685. {
  686.   int       rover;
  687.  
  688.   for (rover = 0; rover < VirtSize; rover++)
  689.     if (strCmpU (VRoomTab[rover].vrName, name) == SAMESTRING)
  690.       return rover;
  691.  
  692.   return ERROR;
  693. }
  694.  
  695. /*
  696.  * VirtualShared()
  697.  *
  698.  * This function returns an index into current net's virtual index.
  699.  */
  700. int
  701. VirtualShared (int NetNo, label name)
  702. {
  703.   int       rover,
  704.             VirtNo;
  705.  
  706.   if ((VirtNo = VirtualExists (name)) == ERROR)
  707.     return ERROR;
  708.  
  709.   for (rover = 0; rover < VIRT_LIMIT; rover++)
  710.     if (VirtNetList[NetNo].VirtList[rover].WhichVirt == VirtNo)
  711.       return rover;
  712.   return ERROR;
  713. }
  714.  
  715. /*********** These functions stolen & modified from MSG.C ***************/
  716.  
  717. /*
  718.  * doActualWrite()
  719.  *
  720.  * This should allow automatic bkp of msg file from RAM.
  721.  */
  722. char
  723. doActualWrite (FILE *whichmsg, struct mBuf *mFile, char c)
  724.   {
  725.   MSG_NUMBER temp;
  726.   int       toReturn = 0;
  727.  
  728.   if (mFile->sectBuf[mFile->thisChar] == 0xFF)
  729.     {
  730.  /* obliterating a msg   */
  731.       toReturn = 1;
  732.     }
  733.  
  734.   mFile->sectBuf[mFile->thisChar] = c;
  735.  
  736.   mFile->thisChar = ++mFile->thisChar % MSG_SECT_SIZE;
  737.  
  738.   if (mFile->thisChar == 0)
  739.     {   /* time to write sector out and get next: */
  740.       temp = mFile->thisSector;
  741.       temp *= MSG_SECT_SIZE;
  742.       fseek (whichmsg, temp, 0);
  743.       crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  744.       if (fwrite (mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  745.         {
  746.           crashout ("?putMsgChar-write fail");
  747.         }
  748.  
  749.       mFile->thisSector = ++mFile->thisSector % cfg.maxMSector;
  750.       temp = mFile->thisSector;
  751.       temp *= MSG_SECT_SIZE;
  752.       fseek (whichmsg, temp, 0);
  753.       if (fread (mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  754.         {
  755.           crashout ("?putMsgChar-read fail");
  756.         }
  757.       crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  758.     }
  759.   return (char) toReturn;
  760. }
  761.  
  762. /*
  763.  * doFlush()
  764.  *
  765.  * This will do actual writeup for specified msg file.
  766.  */
  767. void
  768. doFlush (whichmsg, mFile)
  769.   FILE     *whichmsg;
  770.   struct mBuf *mFile;
  771. {
  772.   long int  s;
  773.  
  774.   s = mFile->thisSector;
  775.   s *= MSG_SECT_SIZE;
  776.   fseek (whichmsg, s, 0);
  777.   crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  778.   if (fwrite (mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  779.     {
  780.       crashout ("?ctdlmsg.sys write fail");
  781.     }
  782.   crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  783.   fflush (whichmsg);
  784. }
  785.  
  786. /*
  787.  * flushMsgBuf()
  788.  *
  789.  * This wraps up writing a message to disk, takes into account 2nd msg file if
  790.  * necessary.
  791.  */
  792. void
  793. flushMsgBuf ()
  794. {
  795.   doFlush (msgfl, &mFile1);
  796.   if (cfg.BoolFlags.mirror)
  797.     doFlush (msgfl2, &mFile2);
  798. }
  799.  
  800. /*
  801.  * putMessage()
  802.  *
  803.  * This function stores a message to disk.
  804.  * Always called before noteMessage() -- newest not ++ed yet.
  805.  * Returns: TRUE on successful save, else FALSE
  806.  */
  807. void
  808. PutMessage ()
  809. {
  810.   char     temp[150];
  811.   extern char *ALL_LOCALS,
  812.            *WRITE_LOCALS;
  813.   extern char *R_SH_MARK,
  814.            *LOC_NET,
  815.            *NON_LOC_NET;
  816.   char     *s;
  817.  
  818.   startAt (msgfl, &mFile1, cfg.catSector, cfg.catChar);
  819. /* tell putMsgChar where to write   */
  820.   if (cfg.BoolFlags.mirror)
  821.     startAt (msgfl2, &mFile2, cfg.catSector, cfg.catChar);
  822.  
  823.   putMsgChar (0xFF);    /* start-of-message     */
  824.  
  825. /* write message ID */
  826.   sPrintf (temp, "%lu", cfg.newest + 1);
  827.   AddField (0, temp);
  828.  
  829. /* write date:      */
  830.   if (msgBuf.mbdate[0])
  831.     {
  832.       AddField ('D', msgBuf.mbdate);
  833.     }
  834.   else
  835.     {
  836.       AddField ('D', "????");
  837.     }
  838.  
  839. /* write time:      */
  840.   if (msgBuf.mbtime[0])
  841.     {
  842.       AddField ('C', msgBuf.mbtime);
  843.     }
  844.   else
  845.     {
  846.       AddField ('C', "!!!!");
  847.     }
  848.  
  849. /* write author's name out: */
  850.   if (msgBuf.mbauth[0])
  851.     {
  852.       AddField ('A', msgBuf.mbauth);
  853.     }
  854.  
  855. /* write room name out:     */
  856.   AddField ('R', msgBuf.mbroom);
  857.  
  858.   if (msgBuf.mbto[0])
  859.     {   /* private message -- write addressee   */
  860.       AddField ('T', msgBuf.mbto);
  861.     }
  862.  
  863.   if (msgBuf.mbaddr[0])
  864.     {   /* net message routing  */
  865.       if (strCmpU (msgBuf.mbaddr, R_SH_MARK) == SAMESTRING ||
  866.           strCmpU (msgBuf.mbaddr, NON_LOC_NET) == SAMESTRING)
  867.         {
  868.           AddField ('N', msgBuf.mboname);
  869.           if (msgBuf.mborig[0])
  870.             {
  871.               AddField ('O', msgBuf.mborig);
  872.             }
  873.           roomTab[thisRoom].rtlastNet = cfg.newest + 1;
  874.         }
  875.       else if (strCmpU (msgBuf.mbaddr, LOC_NET) == SAMESTRING)
  876.         {
  877.           AddField ('N', msgBuf.mboname);
  878.           if (msgBuf.mborig[0])
  879.             {
  880.               AddField ('O', msgBuf.mborig);
  881.             }
  882.         }
  883.  
  884.       sPrintf (temp, "%s%d", msgBuf.mbaddr, thisNet);
  885.       AddField ('Q', temp);
  886.     }
  887.   else
  888.     {
  889.       if (msgBuf.mboname[0])
  890.         {
  891.           AddField ('N', msgBuf.mboname);
  892.         }
  893.       if (msgBuf.mborig[0])
  894.         {
  895.           AddField ('O', msgBuf.mborig);
  896.         }
  897.     }
  898.  
  899.   if (msgBuf.mbdomain[0])
  900.     {
  901.       AddField ('X', msgBuf.mbdomain);
  902.     }
  903.  
  904.   if (msgBuf.mbsrcId[0])
  905.     {
  906.       AddField ('S', msgBuf.mbsrcId);
  907.     }
  908.  
  909.   if (msgBuf.mbOther[0])
  910.     {
  911.       AddField ('P', msgBuf.mbOther);
  912.     }
  913.  
  914. /* write message text by hand because it would overrun AddField buffer: */
  915.   putMsgChar ('M');     /* M-for-message.       */
  916.   for (s = msgBuf.mbtext; *s; s++)
  917.     putMsgChar (*s);
  918.  
  919.   putMsgChar (0);       /* null to end text     */
  920.   flushMsgBuf ();
  921.  
  922. }
  923.  
  924. /*
  925.  * AddField()
  926.  *
  927.  * This adds a field to the message base.
  928.  */
  929. void
  930. AddField (field, fValue)
  931.   int       field;
  932.   char     *fValue;
  933. {
  934.   int i=0;
  935.   if( debug_flag )
  936.     {
  937.     if( field)
  938.       printf("   %c:%s(",field, fValue);
  939.     else
  940.       printf("NULL:%s(",fValue);
  941.     };
  942.   if (field)
  943.     putMsgChar (field);
  944.   while (*fValue)
  945.     {
  946.     putMsgChar (*fValue++);
  947.     i++;
  948.     };
  949.   putMsgChar (0);       /* End field. */
  950.   if( debug_flag)printf("%d characters)\n", i);
  951. }
  952.  
  953. /*
  954.  * putMsgChar()
  955.  *
  956.  * This function writes successive message chars to disk.
  957.  * Globals:     thisChar=       thisSector=
  958.  * Returns:     ERROR if problems else TRUE.
  959.  */
  960. int
  961. putMsgChar (c)
  962.   int       c;
  963. {
  964.   int       toReturn;
  965.   int       count1,
  966.             count2;
  967.  
  968.   toReturn = TRUE;
  969.   count1 = doActualWrite (msgfl, &mFile1, c);
  970.   if (cfg.BoolFlags.mirror)
  971.     {
  972.       count2 = doActualWrite (msgfl2, &mFile2, c);
  973.       if (count1 != count2)
  974.         printf ("Mirror msg count discrepancy!");
  975.     }
  976.   if (count1)
  977.     ++cfg.oldest;
  978.   return toReturn;
  979. }
  980.  
  981. static label SearchResult;
  982. static char *SearchTarget,
  983.           GetAlias;
  984.  
  985. /*
  986.  * UseNetAlias()
  987.  *
  988.  * This function will find a usenet alias or the converse.
  989.  */
  990. char     *
  991. UseNetAlias (char *Name, char FindAlias)
  992. {
  993.   void     *EatTrans ();
  994.   SListBase Dummy =
  995.   {NULL, NULL, NULL, NULL, EatTrans};
  996.   SYS_FILE  fn;
  997.   char     *c;
  998.  
  999.   SearchResult[0] = 0;
  1000.   SearchTarget = Name;
  1001.   if (!FindAlias)
  1002.     while ((c = strchr (Name, ' ')) != NULL)
  1003.       *c = '_';
  1004.   makeSysName (fn, "st-alias.sys", &cfg.roomArea);
  1005.   GetAlias = FindAlias;
  1006.   MakeList (&Dummy, fn, NULL);  /* CHEAT!  WHEEEEEE! */
  1007.   if (strLen (SearchResult) == 0)
  1008.     return NULL;
  1009.   return SearchResult;
  1010. }
  1011.  
  1012. /*
  1013.  * EatTrans()
  1014.  *
  1015.  * This function will eat a line of for the alias mapping.
  1016.  */
  1017. void     *
  1018. EatTrans (char *line)
  1019. {
  1020.   char     *c;
  1021.  
  1022.   if ((c = strchr (line, ' ')) != NULL)
  1023.     {
  1024.       *c = 0;
  1025.       if (GetAlias)
  1026.         {       /* check second field */
  1027.           if (strCmpU (c + 1, SearchTarget) == SAMESTRING)
  1028.             {
  1029.               strCpy (SearchResult, line);
  1030.             }
  1031.         }
  1032.       else
  1033.         {       /* check first field */
  1034.           if (strCmpU (line, SearchTarget) == SAMESTRING)
  1035.             {
  1036.               strCpy (SearchResult, c + 1);
  1037.             }
  1038.         }
  1039.     }
  1040.   return NULL;
  1041. }
  1042.  
  1043. /*
  1044.  * FindRouteSlot()
  1045.  *
  1046.  * This function will find the slot of routing node.  If found, netTemp will
  1047.  * contain the new slot, as will RouteSlot.
  1048.  */
  1049. int
  1050. FindRouteSlot ()
  1051. {
  1052. /*
  1053.  * first check to see if we're the direct (final) link, either
  1054.  * expressly or because the route is outdated.
  1055.  */
  1056.   if (!DirectRoute (&netTemp))  /* expressly?   */
  1057.     getNet ((RouteSlot = netTemp.nbRoute), &netTemp);
  1058.  
  1059.   return RouteSlot;
  1060. }
  1061.  
  1062. /*
  1063.  * DirectRoute()
  1064.  *
  1065.  * This will discover if we directly or indirectly talk to this node.
  1066.  */
  1067. char
  1068. DirectRoute (NetBuffer * n)
  1069. {
  1070.   return (char) (n->nbRoute == -1 ||    /* expressly?   */
  1071.                  !netTab[n->nbRoute].ntflags.in_use ||  /* outdated?    */
  1072.                  netTab[n->nbRoute].ntGen != n->nbRouteGen);    /* outdated? */
  1073. }
  1074.  
  1075. /*
  1076.  * getNetChar()
  1077.  *
  1078.  * This gets a character from a network temporary file.
  1079.  */
  1080. int
  1081. getNetChar ()
  1082. {
  1083.   return -1;    /* actually, this should never be called.       */
  1084. }
  1085.  
  1086. /*
  1087.  * SepNameSystem()
  1088.  *
  1089.  * This will parse an Other Recipient spec.
  1090.  */
  1091. char
  1092. SepNameSystem (char *string, char *person, char *system, NetBuffer * buf)
  1093. {
  1094.   char     *c;
  1095.   int       n;
  1096.   char      work[NAMESIZE * 3];   /* should be sufficient */
  1097.  
  1098.   strCpy (work, string);
  1099.   if ((c = strchr (work, '@')) == NULL)
  1100.     return NOT_SYSTEM;
  1101.  
  1102. /* find leading spaces of "name @ system" format */
  1103.   for (n = 1; c[n] == ' ' && c[n]; n++)
  1104.     ;
  1105.  
  1106.   if (strLen (c + n) >= NAMESIZE)
  1107.     return BAD_FORMAT;
  1108.  
  1109.   strCpy (system, c + n);
  1110.   if (searchNameNet (c + n, buf) == ERROR)      /* bad - set signal of it */
  1111.     return NO_SYSTEM;
  1112.  
  1113.   *c = 0;
  1114.   CleanEnd (work);      /* kill trailing spaces */
  1115.   if (strLen (work) >= NAMESIZE)
  1116.     return BAD_FORMAT;
  1117.  
  1118.   strCpy (person, work);
  1119.  
  1120.   return IS_SYSTEM;
  1121. }
  1122.  
  1123. #define WeServe(x)      SearchList(&Serves, x)
  1124. extern SListBase Serves;
  1125.  
  1126. /*
  1127.  * LocalName()
  1128.  *
  1129.  * This takes a string of form <system> _ <domain> and attempts to discover if
  1130.  * this domain mapped system is actually a local.  This is used when we're
  1131.  * sending mail and are trying to find out if a Who Else override needs to be
  1132.  * generated.  Ugly kludge, but, hey, that's what programming's all about, eh?
  1133.  */
  1134. char     *
  1135. LocalName (char *system)
  1136. {
  1137.   char     *domain,
  1138.            *System;
  1139.  
  1140.   if ((domain = strchr (system, '_')) == NULL)
  1141.     return system;
  1142.   domain += 2;  /* always preceded by a space -- or so we assume */
  1143.  
  1144.   if (strCmpU (domain, cfg.codeBuf + cfg.nodeDomain) == SAMESTRING ||
  1145.       WeServe (domain) != NULL)
  1146.     {
  1147.       System = strdup (system);
  1148.       if ((domain = strchr (System, ' ')) == NULL)
  1149.         return system;  /* should never happen, though */
  1150.       *domain = NULL;
  1151.       if (searchNameNet (System, &netTemp) != ERROR)
  1152.         {
  1153.           free (System);
  1154.           return netTemp.netName;
  1155.         }
  1156.       free (System);
  1157.     }
  1158.   return system;
  1159. }
  1160.  
  1161. /*
  1162.  * mFormat()
  1163.  *
  1164.  * This function formats a string to modem and console.
  1165.  */
  1166. void
  1167. mFormat (char *string)
  1168. {
  1169.   char      wordBuf[MAXWORD];
  1170.   int       i;
  1171.  
  1172.   for (i = 0; string[i];)
  1173.     {
  1174.       i = getWord (wordBuf, string, i, MAXWORD);
  1175.       putWord (wordBuf);
  1176.     }
  1177. }
  1178.  
  1179. /*
  1180.  * getWord()
  1181.  *
  1182.  * This function fetches one word from current message.
  1183.  */
  1184. int
  1185. getWord (char *dest, char *source, int offset, int lim)
  1186. {
  1187.   int       i,
  1188.             j;
  1189.  
  1190. /* skip leading blanks if any */
  1191.   for (i = 0; source[offset + i] == ' ' && i < lim - 1; i++) ;
  1192.  
  1193. /* step over word */
  1194.   for (;
  1195.  
  1196.        source[offset + i] != ' ' &&
  1197.        i < lim - 1 &&
  1198.        source[offset + i] != 0;
  1199.  
  1200.        i++
  1201.     ) ;
  1202.  
  1203.   if (source[offset + i - 1] != '\n')
  1204.  
  1205. /* pick up any trailing blanks */
  1206.     for (; source[offset + i] == ' ' && i < lim - 1; i++) ;
  1207.  
  1208. /* copy word over */
  1209.   for (j = 0; j < i; j++)
  1210.     dest[j] = source[offset + j];
  1211.   dest[j] = 0;  /* null to tie off string */
  1212.  
  1213.   return (offset + i);
  1214. }
  1215.  
  1216. /*
  1217.  * putWord()
  1218.  *
  1219.  * This function writes one word to modem & console.
  1220.  */
  1221. void
  1222. putWord (char *st)
  1223. {
  1224.   char     *s;
  1225.   int       newColumn;
  1226.   static char prevChar = 0;
  1227.  
  1228.   for (newColumn = crtColumn, s = st; *s; s++)
  1229.     {
  1230.       if (*s != TAB)
  1231.         {
  1232.           if (*s == '\b')
  1233.             newColumn--;
  1234.           else
  1235.             ++newColumn;
  1236.         }
  1237.       else
  1238.         while (++newColumn % 8) ;
  1239.     }
  1240.   if (newColumn > termWidth)
  1241.     {
  1242.       fprintf (upfd, "\n");
  1243.       crtColumn = 1;
  1244.     }
  1245.  
  1246.   for (; *st; st++)
  1247.     {
  1248.  
  1249.       if (*st != TAB)
  1250.         {
  1251.           if (*st == '\b')
  1252.             crtColumn--;
  1253.           else
  1254.             ++crtColumn;
  1255.         }
  1256.       else
  1257.         while (++crtColumn % 8) ;
  1258.  
  1259.  /* worry about words longer than a line:        */
  1260.       if (crtColumn > termWidth)
  1261.         {
  1262.           fprintf (upfd, "\n");
  1263.           crtColumn = 1;
  1264.         }
  1265.  
  1266.       if (*st == '\n' && EOP)
  1267.         {
  1268.           fprintf (upfd, "\n");
  1269.           crtColumn = 1;
  1270.         }
  1271.       else if (prevChar != NEWLINE || (*st > ' '))
  1272.         {
  1273.           putc (*st, upfd);
  1274.           prevChar = *st;
  1275.           if (*st > ' ')
  1276.             EOP = FALSE;
  1277.         }
  1278.       else
  1279.         {
  1280.           fprintf (upfd, "\n");
  1281.           crtColumn = 1;
  1282.           if (*st == '\n' && !EOP)
  1283.             {
  1284.               fprintf (upfd, "\n");
  1285.               crtColumn = 1;
  1286.             }
  1287.           else
  1288.             putc (*st, upfd), prevChar = *st;
  1289.           EOP = TRUE;
  1290.         }
  1291.     }
  1292. }
  1293.  
  1294. /*
  1295.    * TranslateFilename()
  1296.    *
  1297.    * This does translations on a filename.  This is used for embedding dates
  1298.    * or numbers into a filename.
  1299.  */
  1300. void
  1301. TranslateFilename (char *realfn, char *fn)
  1302. {
  1303.   int       year,
  1304.             day,
  1305.             hours,
  1306.             minutes;
  1307.   char     *month;
  1308.  
  1309.   getCdate (&year, &month, &day, &hours, &minutes);
  1310.   *realfn = '\0';
  1311.   while (*fn)
  1312.     {
  1313.       if (*fn == '%')
  1314.         {
  1315.           fn++;
  1316.           switch (*fn)
  1317.             {
  1318.               case 'm':
  1319.               case 'M':
  1320.                 sPrintf (realfn, "%s", month);
  1321.                 realfn += 3;
  1322.                 break;
  1323.               case 'y':
  1324.               case 'Y':
  1325.                 sPrintf (realfn, "%d", year);
  1326.                 realfn += 2;
  1327.                 break;
  1328.             };
  1329.           fn++;
  1330.         }
  1331.       else
  1332.         {
  1333.           *realfn++ = *fn++;
  1334.         };
  1335.       *realfn = '\0';
  1336.     }
  1337. }
  1338.  
  1339. void
  1340. netResult (char *msg)
  1341. {
  1342.   printf ("%s\n", msg);
  1343. }
  1344.  
  1345. char     *MonthTab[] =
  1346. {
  1347.   "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
  1348.   "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
  1349.  
  1350. };
  1351.  
  1352. char     *KeyWords[] =
  1353. {
  1354.   "TODAY", "YESTERDAY"
  1355.  
  1356. };
  1357.  
  1358. char      DayPMonth[] =
  1359. {
  1360.   31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1361.  
  1362. };
  1363.  
  1364. /*
  1365.  * getCdate()
  1366.  *
  1367.  * This retrieves system date and returns in the parameters.
  1368.  */
  1369. void
  1370. getCdate (int *year, char **month, int *day, int *hours, int *minutes)
  1371. {
  1372.   int       mon,
  1373.             seconds,
  1374.             milli;
  1375.  
  1376.   getRawDate (year, &mon, day, hours, minutes, &seconds, &milli);
  1377.   *year -= 1900;
  1378.   *month = MonthTab[mon];
  1379.  
  1380. }
  1381.  
  1382. void      Do_Stack_Check (void);
  1383.  
  1384. #define LeapYear(x)     ((x % 4) ? FALSE : ((year % 100) ? TRUE : FALSE))
  1385. /************************************************************************/
  1386. /*      ReadDate() interprets the string and returns it in seconds      */
  1387. /************************************************************************/
  1388. int
  1389. ReadDate (char *date, long *RetTime)
  1390. {
  1391.   int       rover,
  1392.             found,
  1393.             keyword = -1;
  1394.   int       year,
  1395.             month,
  1396.             day,
  1397.             hours,
  1398.             minutes,
  1399.             seconds,
  1400.             milli;
  1401.   label     mon;
  1402.   char     *d = date;
  1403.   char      darray[6];            /* see format for utpack() */
  1404.  
  1405.   Do_Stack_Check ();
  1406.   if (strLen (date) == 0)
  1407.     return FALSE;
  1408.   if (isdigit (date[0]))
  1409.     {
  1410.       darray[0] = (char) (atoi (date) + 1900 - 1970);
  1411.       while (isdigit (*date))
  1412.         date++;
  1413.  
  1414.     }
  1415.   else
  1416.     {
  1417.       getRawDate (&year, &month, &day, &hours, &minutes,
  1418.                   &seconds, &milli);
  1419.       year -= 1970;
  1420.       darray[0] = (char) year;
  1421.       darray[1] = (char) month;
  1422.       darray[2] = (char) day;
  1423.  
  1424.     }
  1425.   for (rover = 0; isalpha (*date); date++, rover++)
  1426.     mon[rover] = toUpper (*date);
  1427.   mon[rover] = 0;
  1428.   if (rover == 0)
  1429.     {
  1430.       if (isdigit (d[0]))
  1431.         {
  1432.           *RetTime = CurAbsolute () - (atol (d) * 86400l);
  1433.           return TRUE;
  1434.         }
  1435.       return ERROR;
  1436.     };
  1437.   for (found = rover = 0; rover < NumElems (MonthTab); rover++)
  1438.     if (strncmp (mon, MonthTab[rover], strLen (mon)) == SAMESTRING)
  1439.       {
  1440.         found++;
  1441.         darray[1] = (char) (rover + 1);
  1442.  
  1443.       }
  1444.   if (found != 1)
  1445.     {
  1446.       for (keyword = -1, rover = 0; rover < NumElems (KeyWords); rover++)
  1447.         if (strncmp (mon, KeyWords[rover], strLen (mon)) == SAMESTRING)
  1448.           {
  1449.             keyword = rover;
  1450.  
  1451.           }
  1452.       if (keyword == -1)
  1453.         return ERROR;
  1454.       else
  1455.         {
  1456.           switch (keyword)
  1457.             {
  1458.               case 0:   /* TODAY */
  1459.                 break;
  1460.               case 1:   /* YESTERDAY */
  1461.                 --darray[2];
  1462.                 if (!darray[2])
  1463.                   {
  1464.                     --darray[1];
  1465.                     if (!darray[1])
  1466.                       {
  1467.                         darray[1] = 12;
  1468.                         --darray[0];
  1469.  
  1470.                       }
  1471.                     darray[2] = DayPMonth[darray[1] - 1];
  1472.                     if (darray[1] == 2 && LeapYear (darray[0]))
  1473.                       darray[2] = 29;
  1474.  
  1475.                   }
  1476.                 break;
  1477.  
  1478.             }
  1479.  
  1480.         }
  1481.  
  1482.     }
  1483.   if ((keyword == -1) && ((darray[2] = (char) atoi (date)) == 0))
  1484.     return ERROR;
  1485.   darray[3] = 0;
  1486.   darray[4] = 0;
  1487.   darray[5] = 0;
  1488.   *RetTime = utpack (darray);
  1489.   return TRUE;
  1490.  
  1491. }
  1492.  
  1493. /************************************************************************/
  1494. /*      CurAbsolute() current time in absolute terms.                   */
  1495. /************************************************************************/
  1496. long
  1497. CurAbsolute ()
  1498. {
  1499.   Do_Stack_Check ();
  1500.   return time (NULL);
  1501.  
  1502. }
  1503.  
  1504. /**
  1505.   Check Routing Address
  1506.  
  1507.   This function will check to see if we have a node address
  1508.   that is not ourselve, or NULL.
  1509. **/
  1510.  
  1511. char Check_Address(label mbaddr )
  1512.   {
  1513.   char new[130];
  1514.   char ours[130];
  1515.   int i;
  1516.   if( (i=strlen(mbaddr)) == 0 ) return FALSE;
  1517.   /**
  1518.     Check to see if the node address is really ourselves
  1519.     or an alias...
  1520.   **/
  1521.   Fix_Name(new,  mbaddr,1);
  1522.   Fix_Name(ours, &cfg.codeBuf[cfg.nodeName],1);
  1523.   if( strncmp(new, ours, strlen(ours)) == 0 )return FALSE;
  1524.   return TRUE;
  1525.   }
  1526.  
  1527.